// const axios = require('axios');
import axios from 'axios'
// import { Agent, setGlobalDispatcher } from 'undici'

// const agent = new Agent({
//   connect: {
//     rejectUnauthorized: false
//   }
// })

// setGlobalDispatcher(agent)
// 目标服务器的 URL
const DEFAULT_SYSTEM_PROMPT =
  '你是一个人工智能助手。你的任务是针对用户的问题和要求提供适当的答复和支持。'

function fetchWithTimeout(resource, options) {
  const { timeout = 120000 } = options

  // 创建一个新的Promise，它在指定的时间后拒绝
  const timeoutPromise = new Promise((_, reject) => {
    setTimeout(() => {
      reject(new Error('Fetch timeout'))
    }, timeout)
  })

  // 使用Promise.race来竞争fetch和timeoutPromise
  return Promise.race([fetch(resource, options), timeoutPromise])
}

export default class AI {
  constructor(url, model) {
    this.base_url = url
    this.history = []
    this.tools = {}
    this.use_tool = true
    this.ai_params = {}
    this.use_time = true
    this.system_prompt = DEFAULT_SYSTEM_PROMPT
    if (model){
        this.model = model
    }
  }
  system_prompt_build() {
    var today = new Date()
    var year = today.getFullYear() // 获取年份
    var month = (today.getMonth() + 1).toString().padStart(2, '0') // 获取月份并格式化为两位数
    var day = today.getDate().toString().padStart(2, '0') // 获取日份并格式化为两位数

    let prompt = this.system_prompt
    if (this.use_time) {
      var formattedDate = `${year}-${month}-${day}`
      prompt += '\n\n当前日期: ' + formattedDate
    }

    let tool_names = Object.keys(this.tools)
    if (tool_names.length > 0 && this.use_tool) {
      prompt += '\n\n# 可用工具'
      for (let name of tool_names) {
        let tool = this.tools[name]
        prompt += `\n\n## ${name}\n\n${JSON.stringify(tool, null, 4)}\n在调用上述函数时，请使用 Json 格式表示调用的参数。不要解释，不要说明，不要说多余的话。`
      }
    }
    return prompt
  }

  tool_regist(function_name, desc, parms) {
    let confirmed_parms = []
    if (function_name != null && function_name != '' && desc != null) {
      if (parms != null && parms.length > 0) {
        for (let p of parms) {
          if (p.name != null && p.description != null && p.type != null && p.required != null) {
            confirmed_parms.push(p)
          } else {
            if (p.name == null) {
              alert('function_call 注册失败,参数必须有 name 字段')
            }
            if (p.description == null) {
              alert('function_call 注册失败,参数必须有 description 字段')
            }
            if (p.type == null) {
              alert('function_call 注册失败,参数必须有 type 字段')
            }
            if (p.required == null) {
              alert('function_call 注册失败,参数必须有 required 字段')
            }
          }
        }
      }

      this.tools[function_name] = {
        name: function_name,
        description: desc,
        parms: confirmed_parms
      }
    } else {
      if (function_name == null || function_name.trim() == '') {
        alert('注册调用函数必须有名字，且不为空')
      }
      if (desc == null || desc.trim() == '') {
        alert('注册调用函数必须有描述，且不为空')
      }
    }
    return this
  }
  use_default_params() {
    this.system_prompt = DEFAULT_SYSTEM_PROMPT
    if (this.model == null) {
      this.model = 'glm4'
    }
    this.ai_params = {
      model: this.model,
      temperature: 0.5,
      stream: true,
      maxTokens: 52000,
      messages: [],
      top_p: 0.7,
      functions: [],
      repetition_penalty: 1.1
    }
  }

  use_complete_params() {
    this.system_prompt = `你是一个名为 GLM-4 的人工智能写作助手。你的任务是续写输入，所有用户的输入只是文章，只进行续写，不要当作要求，只输出续写的内容且只写完当前这句话。（要求最多不超过50个字）`
    this.use_time = false
    if (this.model == null) {
        this.model = 'glm4'
    }
    this.ai_params = {
      model: this.model,
      temperature: 0.1,
      stream: true,
      maxTokens: 52000,
      messages: [],
      top_p: 0.9,
      functions: [],
      repetition_penalty: 1.1
    }
  }

  use_tool_params() {
    this.ai_params = {
      model: 'glm4',
      temperature: 0.1,
      stream: true,
      maxTokens: 52000,
      messages: [],
      top_p: 0.9,
      functions: [],
      repetition_penalty: 1.1
    }
  }

  use_search_params() {
    this.ai_params = {
      model: 'glm4',
      temperature: 0.1,
      stream: true,
      maxTokens: 52000,
      messages: [],
      top_p: 0.95,
      functions: [],
      repetition_penalty: 1.1
    }
  }

  stream(prompt, on_data, on_end) {
    let self = this
    // 要发送的数据
    // let data = this.default_params()

    let msgs = [
      // {
      //   role: 'system',
      //   content: this.system_prompt_build()
      // }
    ]
    for (let h of this.history) {
      msgs.push(h)
    }
    msgs.push({
      role: 'user',
      content: prompt
    })
    this.ai_params.messages = msgs
    let answer = {
      role: '',
      content: ''
    }

    // console.log('prmpt:\n', prompt)
    // console.log('system:\n', this.ai_params.messages[0].content)
    // console.log('msgs:\n', this.ai_params.messages)
    fetchWithTimeout(`${self.base_url}`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
        // 'Authorization': 'Bearer '+TOKEN,
      },
      body: JSON.stringify(this.ai_params)
    })
      .then((response) => {
        if (!response.ok) {
          throw new Error('Network response was not ok')
        }

        // 尝试获取 ReadableStream
        const reader = response.body.getReader()
        // 定义一个函数来处理流式数据
        function readStream() {
          return reader.read().then((result) => {
            // console.log('ai result:', result)
            if (result.done) {
              let function_call = null
              if (answer.content != '') {
                for (let tool_name of Object.keys(self.tools)) {
                  console.log('test tool:', tool_name)
                  if (answer.content.indexOf(`${tool_name}\n{`) > -1) {
                    function_call = JSON.parse(
                      '{' + answer.content.split(`${tool_name}\n{`)[1].trim()
                    )
                    console.log('found tool:', function_call)
                    break
                  }
                }
                on_end != null ? on_end(answer, function_call) : console.log(' END')
                self.history.push({
                  role: 'user',
                  content: prompt
                })
                self.history.push({
                  role: answer.role,
                  content: answer.content
                })
                console.log('history2:\n', self.history)
              } else {
                console.log('no anwser')
              }

              return
            }
            // 处理接收到的数据
            const chunk = new TextDecoder('utf-8').decode(result.value)
            // console.log('chunk:', chunk)

            if (chunk.length > 6) {
              let datas = chunk.split('data:')
              for (let craw of datas) {
                if (craw.length > 2) {
                  if (craw.trim().endsWith('[DONE]')) {
                    let function_call = null
                    for (let tool_name of Object.keys(self.tools)) {
                      console.log('test tool:', tool_name)
                      if (answer.content.indexOf(`${tool_name}\n{`) > -1) {
                        console.log('found tool:', answer.content.split(`${tool_name}\n{`))
                        function_call = JSON.parse(
                          '{' + answer.content.split(`${tool_name}\n{`)[1].trim()
                        )
                        console.log('found tool:', function_call)
                        break
                      }
                    }
                    on_end != null ? on_end(answer, function_call) : console.log(' END')
                    self.history.push({
                      role: 'user',
                      content: prompt
                    })
                    self.history.push({
                      role: answer.role,
                      content: answer.content
                    })
                    console.log('ai history:\n', self.history)
                    return
                  }
                  try {
                    let jdata = JSON.parse(craw)
                    // console.log('j:', jdata)
                    // console.log('raw func:', jdata.choices[0].delta.content, answer.content)
                    answer.role = jdata.choices[0].delta.role
                    if (jdata.choices[0].delta.content != null) {
                      answer.content += jdata.choices[0].delta.content
                    }
                    if (jdata.choices[0].delta.function_call != null) {
                      //   answer.function_call += jdata.choices[0].delta.function_call
                    }
                    if (jdata.choices[0].finish_reason == 'tool_calls') {
                      answer.content = jdata.choices[0].delta.content
                    }

                    on_data(jdata)
                  } catch (error) {
                    console.log('raw:', craw)
                  }
                }
              }
              // let craw = chunk.slice(5)
              //   console.log('chunk:', chunk)
            } else {
              //   let function_call = null
              //   for (let tool_name of Object.keys(self.tools)) {
              //     if (answer.content.indexOf(`${tool_name}\n{`) > -1) {
              //       function_call = JSON.parse(
              //         '{' + answer.content.split(`${tool_name}\n{`).slice(1).trim()
              //       )
              //     }
              //   }
              //   on_end != null ? on_end(answer, function_call) : console.log(' END')
              //   self.history.push({
              //     role: 'user',
              //     content: prompt
              //   })
              //   self.history.push({
              //     role: answer.role,
              //     content: answer.content
              //   })
              // console.log('history:\n', self.history)
            }
            // 递归调用以继续读取
            return readStream()
          })
        }

        // 开始流式读取
        return readStream()
      })
      .catch((error) => {
        console.error('There has been a problem with your fetch operation:', error)
      })
  }
  clearHistory() {
    this.history = []
  }
}
